#!/usr/bin/python
# -- coding:utf8 --

# 线上部署的代码
import os
import sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import app.model_phl.util_log as utils
from app.model_phl.utils import select_sql_mysql
import app.model_phl.my_tool_package as my_package
import pandas as pd
import numpy as np
# import my_tool_package as my_package
import json
import re
import warnings

warnings.filterwarnings('ignore')

file_path_name1 = './model/app_type_dict_ph_v2.json'
current_path = os.path.dirname(__file__)
file_path_name1 = file_path_name1.replace("./", current_path + "/")
with open(file_path_name1, 'r') as f:
    app_type_dict = json.loads(f.read())


def get_condition_df(df, condition_field, match_list='none'):
    """
    找到满足appname属于某一类别的数据,精确匹配
    :param df:
    :param condition_field:
    :param match_list:
    :return:
    """
    if df.empty:
        return pd.DataFrame()
    df_tmp = df.copy().reset_index()
    # 找到满足时间窗口的数据
    if match_list == 'none':
        return df_tmp
    else:
        return df_tmp[df_tmp[condition_field].isin(match_list)]


def get_list_value_is_in_str(match_list, params_str):
    """
    检查字符串是否匹配了目标列表
    :param match_list:
    :param params_str:
    :return:
    """
    for v in match_list:
        if type(v) == list:
            flg = 1
            for v_ in v:
                if str(v_).strip().lower() not in str(params_str).strip().lower():
                    flg = 0
            if flg == 1:
                return 1
        else:
            if str(v).strip().lower() in str(params_str).strip().lower():
                return 1
    return 0


def get_condition_fuzzy_df(df, condition_field, match_list='none'):
    """
    找到满足appname属于某一类别的数据,模糊匹配
    :param df:
    :param condition_field:
    :param match_list:
    :return:
    """
    if df.empty:
        return df
    df_tmp = df.copy().reset_index()
    # 找到满足时间窗口的数据
    if match_list == 'none':
        return df_tmp
    else:
        return df_tmp[df_tmp[condition_field].apply(lambda x: get_list_value_is_in_str(match_list, x) == 1)]


def get_windows_aggregation_main(df, con, dt, con_key, cal_field, cal_type, condition_dict_all, dt_dict):
    """
    统计聚合函数
    :param df:
    :param con:
    :param dt:
    :param con_key:
    :param cal_field:
    :param cal_type:
    :param condition_dict_all:
    :param dt_dict:
    :return:
    """
    df_tmp = df.copy()
    df_tmp[cal_field] = df_tmp[cal_field].apply(lambda x: np.nan if (my_package.get_is_none(x) == True) else x)
    default_list = [cal_field]
    df_time_tmp = df_tmp[dt_dict[dt]]
    if df_time_tmp.empty:
        df_time_tmp = pd.DataFrame(columns=default_list)
    df_con_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt] & condition_dict_all[con_key]]
    df_con_tmp = df_con_tmp[pd.isnull(df_con_tmp[cal_field]) == False]
    if df_con_tmp.empty:
        df_con_tmp = pd.DataFrame(columns=default_list)
    if cal_type == 'Cnt':
        re_value = df_con_tmp[cal_field].count()
        if df_con_tmp.empty:
            re_value = -999999
    elif cal_type == 'DistinctCnt':
        re_value = df_con_tmp[cal_field].nunique()
        if df_con_tmp.empty:
            re_value = -999999
    elif cal_type == 'RepeatCnt':
        unique_cnt = df_con_tmp[cal_field].nunique()
        _cnt = df_con_tmp[cal_field].count()
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = _cnt - unique_cnt
    elif cal_type == 'Std':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].std(), 2)
    elif cal_type == 'Avg':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].mean(), 2)
    elif cal_type == 'Max':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].max(), 2)
    elif cal_type == 'Min':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].min(), 2)
    elif cal_type == 'Sum':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].sum(), 2)
    elif cal_type == 'Pct':
        df_dem_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].count()
        num = df_con_tmp[cal_field].count()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, dem)
    elif cal_type == 'PctV2':
        df_dem_tmp = df_tmp[condition_dict_all[con_key] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].count()
        num = df_con_tmp[cal_field].count()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, dem)
    elif cal_type == 'DistinctPct':
        dem = df_con_tmp[cal_field].count()
        num = df_con_tmp[cal_field].nunique()
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, dem)
    elif cal_type == 'NuniquePct':
        df_dem_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].nunique()
        num = df_con_tmp[cal_field].nunique()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, dem)
    elif cal_type == 'NuniquePctV2':
        df_dem_tmp = df_tmp[condition_dict_all[con_key] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].nunique()
        num = df_con_tmp[cal_field].nunique()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, dem)
    elif cal_type == 'RepeatPct':
        cnt_dem = df_con_tmp[cal_field].count()
        unique_cnt_num = df_con_tmp[cal_field].nunique()
        num = cnt_dem - unique_cnt_num
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = my_package.get_cal_division(num, cnt_dem)
    elif cal_type == 'Median':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].median(), 2)
    elif cal_type == 'Skew':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].skew(), 2)
    elif cal_type == 'Mad':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].mad(), 2)
    else:
        re_value = -999999
    if str(re_value).lower().strip() in ['nan']:
        re_value = -999999
    return re_value


def get_label_content(x, key_dict, cal_list):
    """
    文本打上关键词标签
    :param x:
    :param key_dict:
    :param cal_list:
    :return:
    """
    label_list = ['All']
    for key in cal_list:
        if key == 'All':
            continue
        else:
            match_list = key_dict[key]
            if get_list_value_is_in_str(match_list, x) == 1:
                label_list.append(key)
    return list(set(label_list))


def get_mysql_data(phone_sub, ApplyNO):
    """
    根据手机号后两位数字和订单号从MySQL数据库获取数据
    :param phone_sub:
    :param ApplyNO:
    :return:
    """
    sql_str = f"""
    select 
    AppName
    ,PackageName
    ,InstallationTime as FIRST_INSTALL_TIME
    ,CreateTime as LAST_UPDATE_TIME
    ,InsertTime as APP_CREATE_TIME
    ,ApplyNO as Phone 
    ,TIMESTAMPDIFF(SECOND,InstallationTime,InsertTime) as InstallInterval
    ,TIMESTAMPDIFF(SECOND,CreateTime,InsertTime) as UpdateInterval
    ,TIMESTAMPDIFF(SECOND,InstallationTime,CreateTime) as InstallUpdateInterval
    ,SUBSTRING(InstallationTime,1,10) as InstallDays
    ,SUBSTRING(CreateTime,1,10) as UpdateDays
    ,ThisApplyNO as ApplyNO
    from fk_applist_{phone_sub} 
    where ThisApplyNO = '{ApplyNO}'
    """
    #
    app_data = select_sql_mysql(sql_str)
    return app_data

def get_format_data_v1(df):
    """
    对获取的APP数据做格式化操作
    :param df:
    :return:
    """
    try:
        df_data_info = df
        if df_data_info.empty:
            return pd.DataFrame()
        df_data_info.loc[:, 'IsUpdate'] = df_data_info['InstallUpdateInterval'].apply(lambda x: 0 if x == 0 else 1)
        # 条件标签label
        con_field_list = ['All', 'Gambling', 'Bank', 'Social', 'bad2', 'good1', 'good2', 'Ecommerce', ]
        # df_data_info.loc[:, 'conLabel'] = df_data_info["AppName"].apply(
        #     lambda x: get_label_content(x, app_type_dict, con_field_list))
        df_data_info['AppNameLabel'] = df_data_info["AppName"].apply(
            lambda x: get_label_content(x, app_type_dict, con_field_list))
        df_data_info['PackageNameLabel'] = df_data_info["PackageName"].apply(
            lambda x: get_label_content(x, app_type_dict, con_field_list))
        df_data_info['conLabel'] = df_data_info[['AppNameLabel', 'PackageNameLabel']].apply(
            lambda x: list(set(set(x['AppNameLabel']) | set(x['PackageNameLabel']))), axis=1)

        cal_field_list = ['AppName', 'InstallDays', 'UpdateDays',
                          'InstallInterval', 'UpdateInterval', 'InstallUpdateInterval']
        for cal_field in cal_field_list:
            df_data_info[cal_field] = df_data_info[cal_field].apply(
                lambda x: np.nan if my_package.get_is_none(x) == True else x)

        return df_data_info
    except Exception as e:
        utils.get_logger().error(e)
        return pd.DataFrame()

def get_free_app_features_v2(phone_sub, ApplyNO):
    """
    根据手机号后两位和订单号获取数据并计算APP特征集
    :param phone_sub:
    :param ApplyNO:
    :return:
    """
    app_df = get_mysql_data(phone_sub, ApplyNO)
    return calculateFreeAppFeaturesV2(app_df)


def calculateFreeAppFeaturesV2(app_df):
    """
    根据手机号后两位和订单号获取数据并计算APP特征集
    :param phone_sub:
    :param ApplyNO:
    :return:
    """
    try:
        df = get_format_data_v1(app_df)
        if df.empty:
            return {
                # 老客模型V1版本
                'appAllGamblingInstallIntervalInstallIntervalMinAllD': -999999,
                'appIsNoUpdateSocialInstallIntervalInstallIntervalMinAllD': -999999,
                'appIsNoUpdateAllInstallIntervalInstallIntervalMedian60D': -999999,
                'appIsNoUpdateBankInstallIntervalInstallIntervalMinAllD': -999999,
                'appIsNoUpdateAllInstallIntervalInstallIntervalMedian30D': -999999,

            }
        df_tmp = df.copy()

        # 筛选符合条件的数据
        con_list_all = ['All', 'Gambling', 'Bank', 'Social', 'IsNoUpdate', 'IsUpdate', 'bad2', 'good1', 'good2', 'Ecommerce', ]
        condition_dict_all = {}
        df_tmp['All'] = 1
        for con in con_list_all:
            if con in ['All']:
                index = df_tmp.All.ge(1)
            elif con in ['IsNoUpdate']:
                index = df_tmp.IsUpdate.eq(0)
            elif con in ['IsUpdate']:
                index = df_tmp.IsUpdate.eq(1)
            else:
                index = df_tmp.conLabel.apply(lambda x: con in x)
            condition_dict_all[con] = index

        # 安装时间条件
        dt_install_dict = {}
        dt_list = ['All', 1, 3, 7, 14, 30, 60]
        for dt in dt_list:
            if dt in ['All']:
                index = df_tmp.All.ge(1)
            else:
                index = df_tmp.InstallInterval.isin(range(0, dt * 24 * 3600))
            dt_install_dict[dt] = index


        # 菲律宾老客模型V1版本
        appAllGamblingInstallIntervalInstallIntervalMinAllD = get_windows_aggregation_main(df_tmp, 'All', 'All',
                                                                                           'Gambling',
                                                                                           'InstallInterval',
                                                                                           'Min',
                                                                                           condition_dict_all,
                                                                                           dt_install_dict)
        appIsNoUpdateSocialInstallIntervalInstallIntervalMinAllD = get_windows_aggregation_main(df_tmp, 'IsNoUpdate',
                                                                                                'All',
                                                                                                'Social',
                                                                                                'InstallInterval',
                                                                                                'Min',
                                                                                                condition_dict_all,
                                                                                                dt_install_dict)
        appIsNoUpdateAllInstallIntervalInstallIntervalMedian60D = get_windows_aggregation_main(df_tmp, 'IsNoUpdate', 60,
                                                                                               'All', 'InstallInterval',
                                                                                               'Median',
                                                                                               condition_dict_all,
                                                                                               dt_install_dict)
        appIsNoUpdateBankInstallIntervalInstallIntervalMinAllD = get_windows_aggregation_main(df_tmp, 'IsNoUpdate',
                                                                                              'All',
                                                                                              'Bank', 'InstallInterval',
                                                                                              'Min',
                                                                                              condition_dict_all,
                                                                                              dt_install_dict)
        appIsNoUpdateAllInstallIntervalInstallIntervalMedian30D = get_windows_aggregation_main(df_tmp, 'IsNoUpdate', 30,
                                                                                               'All', 'InstallInterval',
                                                                                               'Median',
                                                                                               condition_dict_all,
                                                                                               dt_install_dict)



        return {
            # 老客模型V1版本
            'appAllGamblingInstallIntervalInstallIntervalMinAllD': appAllGamblingInstallIntervalInstallIntervalMinAllD,
            'appIsNoUpdateSocialInstallIntervalInstallIntervalMinAllD': appIsNoUpdateSocialInstallIntervalInstallIntervalMinAllD,
            'appIsNoUpdateAllInstallIntervalInstallIntervalMedian60D': appIsNoUpdateAllInstallIntervalInstallIntervalMedian60D,
            'appIsNoUpdateBankInstallIntervalInstallIntervalMinAllD': appIsNoUpdateBankInstallIntervalInstallIntervalMinAllD,
            'appIsNoUpdateAllInstallIntervalInstallIntervalMedian30D': appIsNoUpdateAllInstallIntervalInstallIntervalMedian30D,
        }
    except Exception as e:
        utils.get_logger().error(e)
        return {
            # 老客模型V1版
            'appAllGamblingInstallIntervalInstallIntervalMinAllD': -999976,
            'appIsNoUpdateSocialInstallIntervalInstallIntervalMinAllD': -999976,
            'appIsNoUpdateAllInstallIntervalInstallIntervalMedian60D': -999976,
            'appIsNoUpdateBankInstallIntervalInstallIntervalMinAllD': -999976,
            'appIsNoUpdateAllInstallIntervalInstallIntervalMedian30D': -999976,
        }


if __name__ == '__main__':
    # 测试用例
    phone_sub = 43
    ApplyNO = '169699371854543670'
    app_features1 = get_free_app_features_v2(phone_sub, ApplyNO)
    print(app_features1)


